package shamir;

/**
 *
 * @author Asia
 */
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import util.Utils;

public class ShamirWorker
{
	
	//public static String path = "/home/michau/Desktop/";
    private shamirKey[] generatedShamirKeys;
    private final static int n = 5; // number of generated shares
    private final static int t = 3; // number of shares for solve the secret (t <= n)
    private int numBits; // number of bits of p
    private BigInteger sharedModulus;
    
    private String privKeyPath;
    private String pubKeyPath;
    private String[] privKeyFileNames;
    
    public ShamirWorker(String privKeyPath, String pubKeyPath){
    	this.privKeyPath = privKeyPath;
    	this.pubKeyPath = pubKeyPath;
    	privKeyFileNames = createFileNames(privKeyPath);
    }
    
    private String[] createFileNames( String privOutput )
    {
        String[] privOutTab = new String[ n ];
        for( int i = 0; i < n; i++ )
            privOutTab[ i ] = privOutput.concat( Integer.toString( i ) ).concat( ".txt" );
        return privOutTab;
    }

    private void divideShamir( String secret, String[] tab, int t )
    {
        BigInteger nB = new BigInteger( secret.getBytes() );
        numBits = nB.bitLength() + 1;
        //System.out.println( "Secret before = " + secret );
        // Create key
        BigInteger[] s;
        try
        {
            s = shamir.generateParameters( t, numBits, secret.getBytes() );
        }
        catch( shamirException sE )
        {
            System.err.println( "Error while generate shamir keys 1" );
            return;
        }
        // System.out.println("parameters generated");
        try
        {
            generatedShamirKeys = shamir.generateKeys( n, t, numBits, s );
        }
        catch( shamirException sE )
        {
            System.err.println( "Error while generate shamir keys 2" );
            return;
        }
     
        for( int i = 0; i < n; i++ )
            try
            {
                Utils.saveShamirKey( tab[ i ], generatedShamirKeys[ i ] );
            }
            catch( Exception e )
            {
                System.err.println( "error while saving" );
            }
    }

    /**
     * <p>
     * Calculate Shamir scheme. You need t shares of n for resolve the secret
     * </p>
     */
    public PrivateKey joinShamir( String[] tab )
    {
        shamirKey[] sk2 = new shamirKey[ t ];
        // System.out.println("joining...");
        try
        {
            // select t keys
            for( int i = 0; i < t; i++ )
                sk2[ i ] = Utils.readShamirKey( tab[ i ] );
        }
        catch( Exception e )
        {
            System.err.println( "error while reading" );
        }
        // solve scheme, calculate parameter 0 (secret)
        byte[] des = shamir.calculateLagrange( sk2 );
        // System.out.println("Lagrange calculated...");
        String text = new String( des );
        //System.out.println( "Secret = " + text );
        PrivateKey privKey=Utils.findPrivate(sharedModulus, text);
//        BigInteger exponent = new BigInteger(text);
//        try {
//			Utils.saveToFile(privKeyPath+"poskladaniu", sharedModulus, exponent);
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
        return privKey;
    }

    public void generate()
    {
        try
        {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance( "RSA" );
            kpg.initialize( 1024 );
            KeyPair kp = kpg.genKeyPair();
            KeyFactory fact = KeyFactory.getInstance( "RSA" );
            RSAPublicKeySpec pub = fact.getKeySpec( kp.getPublic(), RSAPublicKeySpec.class );
            RSAPrivateKeySpec priv = fact.getKeySpec( kp.getPrivate(), RSAPrivateKeySpec.class );
            divideShamir( priv.getPrivateExponent().toString(), privKeyFileNames, t );
            Utils.saveToFile( pubKeyPath, pub.getModulus(), pub.getPublicExponent() );
            
            //Utils.saveToFile(privKeyPath+"przedskladaniem", priv.getModulus(), priv.getPrivateExponent());
            sharedModulus=pub.getModulus();
        }
        catch( Exception e )
        {
        	e.printStackTrace();
            System.err.println( "Invalid input" );
        }
    }
}
